import tkinter as tk
from tkinter import ttk, messagebox
import numpy as np
from typing import List, Tuple, Optional
from switch_puzzle_solver import SwitchPuzzleSolver


class ModernSwitchPuzzleGUI:
    def __init__(self, root):
        self.root = root
        self.root.title("三相开关谜题求解器")
        self.root.geometry("1000x750")

        # 设置现代化主题
        self.setup_modern_theme()

        # 默认网格大小
        self.rows = 3
        self.cols = 3

        # 网格按钮
        self.grid_buttons = []

        # 当前选中的状态
        self.current_state = 1

        # 状态颜色映射
        self.state_colors = {
            0: ("#F8F9FA", "#6C757D"),  # 无开关 - 浅灰
            1: ("#DC3545", "#FFFFFF"),  # 关闭 - 红色
            2: ("#FD7E14", "#FFFFFF"),  # 等待 - 橙色
            3: ("#28A745", "#FFFFFF"),  # 开启 - 绿色
            -1: ("#721C24", "#FFFFFF"),  # 不可手动关闭 - 深红
            -2: ("#A0522D", "#FFFFFF"),  # 不可手动等待 - 深橙
            -3: ("#155724", "#FFFFFF"),  # 不可手动开启 - 深绿
        }

        # 状态名称映射
        self.state_names = {
            0: "无开关",
            1: "关闭",
            2: "等待",
            3: "开启",
            -1: "不可关闭",
            -2: "不可等待",
            -3: "不可开启",
        }

        self.create_widgets()
        self.create_grid()

    def setup_modern_theme(self):
        """设置现代化主题"""
        style = ttk.Style()

        # 配置现代化颜色
        style.configure("Modern.TFrame", background="#F8F9FA")
        style.configure(
            "Modern.TLabelframe", background="#F8F9FA", borderwidth=2, relief="flat"
        )
        style.configure(
            "Modern.TLabelframe.Label",
            background="#F8F9FA",
            font=("Microsoft YaHei", 10, "bold"),
        )

        # 简化按钮样式，避免颜色冲突
        style.configure("Modern.TButton", font=("Microsoft YaHei", 9), borderwidth=1)

        style.configure("Success.TButton", font=("Microsoft YaHei", 9), borderwidth=1)

        style.configure("Warning.TButton", font=("Microsoft YaHei", 9), borderwidth=1)

        style.configure("Danger.TButton", font=("Microsoft YaHei", 9), borderwidth=1)

    def create_widgets(self):
        """创建界面组件"""
        # 主容器
        main_container = ttk.Frame(self.root, style="Modern.TFrame", padding="20")
        main_container.pack(fill=tk.BOTH, expand=True)

        # 标题
        title_label = tk.Label(
            main_container,
            text="三相开关谜题求解器",
            font=("Microsoft YaHei", 24, "bold"),
            fg="#212529",
            bg="#F8F9FA",
        )
        title_label.pack(pady=(0, 20))

        # 主要内容区域
        content_frame = ttk.Frame(main_container, style="Modern.TFrame")
        content_frame.pack(fill=tk.BOTH, expand=True)

        # 左侧控制面板
        control_panel = ttk.Frame(content_frame, style="Modern.TFrame")
        control_panel.pack(side=tk.LEFT, fill=tk.Y, padx=(0, 20))

        # 网格配置
        self.create_grid_config(control_panel)

        # 状态选择器
        self.create_state_selector(control_panel)

        # 操作按钮
        self.create_action_buttons(control_panel)

        # 中间网格区域
        grid_panel = ttk.Frame(content_frame, style="Modern.TFrame")
        grid_panel.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 20))

        self.create_grid_panel(grid_panel)

        # 右侧结果区域
        result_panel = ttk.Frame(content_frame, style="Modern.TFrame")
        result_panel.pack(side=tk.RIGHT, fill=tk.BOTH, expand=True)

        self.create_result_panel(result_panel)

    def create_grid_config(self, parent):
        """创建网格配置区域"""
        config_frame = ttk.LabelFrame(
            parent, text="网格配置", style="Modern.TLabelframe", padding="15"
        )
        config_frame.pack(fill=tk.X, pady=(0, 15))

        # 行数设置
        row_frame = ttk.Frame(config_frame)
        row_frame.pack(fill=tk.X, pady=(0, 10))

        ttk.Label(row_frame, text="行数:", font=("Microsoft YaHei", 10)).pack(
            side=tk.LEFT
        )
        self.rows_var = tk.StringVar(value="3")
        self.rows_spinbox = ttk.Spinbox(
            row_frame,
            from_=1,
            to=10,
            width=8,
            textvariable=self.rows_var,
            font=("Microsoft YaHei", 10),
        )
        self.rows_spinbox.pack(side=tk.RIGHT)

        # 列数设置
        col_frame = ttk.Frame(config_frame)
        col_frame.pack(fill=tk.X, pady=(0, 15))

        ttk.Label(col_frame, text="列数:", font=("Microsoft YaHei", 10)).pack(
            side=tk.LEFT
        )
        self.cols_var = tk.StringVar(value="3")
        self.cols_spinbox = ttk.Spinbox(
            col_frame,
            from_=1,
            to=10,
            width=8,
            textvariable=self.cols_var,
            font=("Microsoft YaHei", 10),
        )
        self.cols_spinbox.pack(side=tk.RIGHT)

        # 应用按钮
        apply_btn = tk.Button(
            config_frame,
            text="应用新尺寸",
            bg="#007BFF",
            fg="white",
            font=("Microsoft YaHei", 10),  # 去掉粗体
            relief="flat",
            borderwidth=1,
            command=self.update_grid_size,
        )
        apply_btn.pack(fill=tk.X)

    def create_state_selector(self, parent):
        """创建状态选择器"""
        state_frame = ttk.LabelFrame(
            parent, text="开关状态", style="Modern.TLabelframe", padding="15"
        )
        state_frame.pack(fill=tk.X, pady=(0, 15))

        # 状态按钮网格 - 使用tk.Button确保颜色正确显示
        states = [
            (1, "关闭", "#DC3545", "#FFFFFF"),
            (2, "等待", "#FD7E14", "#FFFFFF"),
            (3, "开启", "#28A745", "#FFFFFF"),
            (-1, "关闭-不可动", "#721C24", "#FFFFFF"),
            (-2, "等待-不可动", "#A0522D", "#FFFFFF"),
            (-3, "开启-不可动", "#155724", "#FFFFFF"),
            (0, "无开关", "#F8F9FA", "#6C757D"),
        ]

        self.state_buttons = []  # 存储状态按钮引用

        for i, (state, name, bg_color, fg_color) in enumerate(states):
            btn = tk.Button(
                state_frame,
                text=name,
                bg=bg_color,
                fg=fg_color,
                font=("Microsoft YaHei", 10),  # 去掉粗体，增大字号
                relief="flat",
                borderwidth=1,
                command=lambda s=state: self.select_state(s),
            )

            # 3-3-1布局：第一行3个，第二行3个，第三行1个
            if i < 3:
                # 第一行：关闭、等待、开启
                btn.grid(row=0, column=i, padx=5, pady=5, sticky="ew")
            elif i < 6:
                # 第二行：关闭-不可动、等待-不可动、开启-不可动
                btn.grid(row=1, column=i - 3, padx=5, pady=5, sticky="ew")
            else:
                # 第三行：无开关（跨越3列居中）
                btn.grid(row=2, column=0, columnspan=3, padx=5, pady=5, sticky="ew")

            btn._state_value = state  # 存储状态值
            self.state_buttons.append(btn)

            # 高亮当前选中的状态
            if state == self.current_state:
                btn.config(relief="sunken")

        # 配置网格权重 - 3列布局
        state_frame.columnconfigure(0, weight=1)
        state_frame.columnconfigure(1, weight=1)
        state_frame.columnconfigure(2, weight=1)

    def create_action_buttons(self, parent):
        """创建操作按钮"""
        action_frame = ttk.LabelFrame(
            parent, text="操作", style="Modern.TLabelframe", padding="15"
        )
        action_frame.pack(fill=tk.X, pady=(0, 15))

        # 清空按钮
        clear_btn = tk.Button(
            action_frame,
            text="清空网格",
            bg="#6C757D",
            fg="white",
            font=("Microsoft YaHei", 10),  # 去掉粗体
            relief="flat",
            borderwidth=1,
            command=self.clear_grid,
        )
        clear_btn.pack(fill=tk.X, pady=(0, 10))

        # 随机生成按钮
        random_btn = tk.Button(
            action_frame,
            text="随机生成",
            bg="#007BFF",
            fg="white",
            font=("Microsoft YaHei", 10),  # 去掉粗体
            relief="flat",
            borderwidth=1,
            command=self.random_grid,
        )
        random_btn.pack(fill=tk.X, pady=(0, 10))

        # 求解按钮
        solve_btn = tk.Button(
            action_frame,
            text="开始求解",
            bg="#28A745",
            fg="white",
            font=("Microsoft YaHei", 10),  # 去掉粗体
            relief="flat",
            borderwidth=1,
            command=self.solve_puzzle,
        )
        solve_btn.pack(fill=tk.X)

    def create_grid_panel(self, parent):
        """创建网格面板"""
        grid_frame = ttk.LabelFrame(
            parent, text="开关网格", style="Modern.TLabelframe", padding="15"
        )
        grid_frame.pack(fill=tk.BOTH, expand=True)

        # 网格容器
        self.grid_container = ttk.Frame(grid_frame)
        self.grid_container.pack(expand=True)

    def create_result_panel(self, parent):
        """创建结果面板"""
        result_frame = ttk.LabelFrame(
            parent, text="求解结果", style="Modern.TLabelframe", padding="15"
        )
        result_frame.pack(fill=tk.BOTH, expand=True)

        # 创建文本框和滚动条
        text_frame = ttk.Frame(result_frame)
        text_frame.pack(fill=tk.BOTH, expand=True)

        self.result_text = tk.Text(
            text_frame,
            font=("Consolas", 9),
            bg="#FFFFFF",
            fg="#212529",
            relief="flat",
            borderwidth=1,
            wrap=tk.WORD,
        )

        scrollbar = ttk.Scrollbar(
            text_frame, orient=tk.VERTICAL, command=self.result_text.yview
        )
        self.result_text.configure(yscrollcommand=scrollbar.set)

        self.result_text.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
        scrollbar.pack(side=tk.RIGHT, fill=tk.Y)

    def select_state(self, state):
        """选择状态"""
        self.current_state = state

        # 更新所有状态按钮的显示
        for btn in self.state_buttons:
            if btn._state_value == state:
                btn.config(relief="sunken")
            else:
                btn.config(relief="flat")

    def update_grid_size(self):
        """更新网格大小"""
        try:
            new_rows = int(self.rows_var.get())
            new_cols = int(self.cols_var.get())

            if new_rows != self.rows or new_cols != self.cols:
                self.rows = new_rows
                self.cols = new_cols
                self.create_grid()
        except ValueError:
            messagebox.showerror("错误", "请输入有效的数字")

    def create_grid(self):
        """创建网格按钮"""
        # 清除现有按钮
        for widget in self.grid_container.winfo_children():
            widget.destroy()

        self.grid_buttons = []

        # 创建网格
        for i in range(self.rows):
            row_buttons = []
            for j in range(self.cols):
                btn = tk.Button(
                    self.grid_container,
                    text="0",
                    width=8,
                    height=4,
                    font=("Microsoft YaHei", 12),  # 去掉粗体，适当减小字号
                    relief="flat",
                    borderwidth=2,
                    command=lambda r=i, c=j: self.on_grid_click(r, c),
                )
                btn.grid(row=i, column=j, padx=3, pady=3, sticky="nsew")
                row_buttons.append(btn)
            self.grid_buttons.append(row_buttons)

        # 配置网格权重
        for i in range(self.rows):
            self.grid_container.grid_rowconfigure(i, weight=1)
        for j in range(self.cols):
            self.grid_container.grid_columnconfigure(j, weight=1)

    def on_grid_click(self, row, col):
        """网格按钮点击事件"""
        button = self.grid_buttons[row][col]
        button.config(text=str(self.current_state))
        self.update_button_color(button, self.current_state)

    def update_button_color(self, button, state):
        """更新按钮颜色"""
        bg_color, fg_color = self.state_colors.get(state, ("#F8F9FA", "#6C757D"))
        button.config(bg=bg_color, fg=fg_color)

    def clear_grid(self):
        """清空网格"""
        for i in range(self.rows):
            for j in range(self.cols):
                button = self.grid_buttons[i][j]
                button.config(text="0", bg="#F8F9FA", fg="#6C757D")

    def random_grid(self):
        """随机生成网格"""
        import random

        states = [0, 1, 2, 3, -1, -2, -3]
        weights = [0.3, 0.2, 0.2, 0.1, 0.1, 0.05, 0.05]

        for i in range(self.rows):
            for j in range(self.cols):
                state = random.choices(states, weights=weights)[0]
                button = self.grid_buttons[i][j]
                button.config(text=str(state))
                self.update_button_color(button, state)

    def get_grid_state(self):
        """获取当前网格状态"""
        grid = []
        for i in range(self.rows):
            row = []
            for j in range(self.cols):
                state = int(self.grid_buttons[i][j].cget("text"))
                row.append(state)
            grid.append(row)
        return grid

    def solve_puzzle(self):
        """求解谜题"""
        try:
            # 获取网格状态
            grid = self.get_grid_state()

            # 清空结果显示
            self.result_text.delete(1.0, tk.END)

            # 显示初始状态
            self.result_text.insert(tk.END, "🎯 初始状态:\n")
            self.result_text.insert(tk.END, self.grid_to_string(grid))
            self.result_text.insert(tk.END, "\n" + "=" * 60 + "\n\n")

            # 创建求解器
            solver = SwitchPuzzleSolver(grid)
            moves = solver.solve()

            if moves:
                self.result_text.insert(
                    tk.END, f"✅ 找到解决方案！需要按动 {len(moves)} 次\n\n"
                )
                self.result_text.insert(tk.END, "📋 具体操作步骤:\n")

                # 模拟每一步
                current_grid = np.array(grid)
                for i, (row, col) in enumerate(moves, 1):
                    self.result_text.insert(
                        tk.END, f"\n🔸 第{i}步：按动位置 ({row+1}, {col+1})\n"
                    )

                    # 模拟这一步
                    if solver.is_manual_switch(row, col):
                        # 改变当前位置
                        v = current_grid[row, col]
                        if v > 0:
                            current_grid[row, col] = v % 3 + 1
                        elif v < 0:
                            current_grid[row, col] = -((-v) % 3 + 1)

                        # 改变相邻位置
                        adjacent_positions = solver.get_adjacent_positions(row, col)
                        for adj_row, adj_col in adjacent_positions:
                            v = current_grid[adj_row, adj_col]
                            if v == 0:
                                continue
                            if v > 0:
                                current_grid[adj_row, adj_col] = v % 3 + 1
                            elif v < 0:
                                current_grid[adj_row, adj_col] = -((-v) % 3 + 1)

                    # 显示当前状态
                    self.result_text.insert(tk.END, f"第{i}步后的状态:\n")
                    self.result_text.insert(
                        tk.END, self.grid_to_string(current_grid.tolist())
                    )

                # 验证最终结果
                final_grid = solver.simulate_moves(moves)
                self.result_text.insert(tk.END, f"\n🎉 最终状态:\n")
                self.result_text.insert(
                    tk.END, self.grid_to_string(final_grid.tolist())
                )

                # 检查是否所有开关都开启
                all_on = True
                for i in range(solver.rows):
                    for j in range(solver.cols):
                        if final_grid[i, j] != 0 and abs(final_grid[i, j]) != 3:
                            all_on = False
                            break

                if all_on:
                    self.result_text.insert(tk.END, "\n🎊 成功！所有开关都已开启！\n")
                else:
                    self.result_text.insert(
                        tk.END, "\n⚠️ 警告：最终状态不正确，可能存在计算错误\n"
                    )

            else:
                self.result_text.insert(tk.END, "❌ 无解！无法将所有开关变为开启状态\n")
                self.result_text.insert(
                    tk.END, "💡 提示：某些初始状态可能无法达到目标状态\n"
                )

        except Exception as e:
            messagebox.showerror("错误", f"求解过程中出现错误：{str(e)}")

    def grid_to_string(self, grid):
        """将网格转换为字符串显示"""
        rows, cols = len(grid), len(grid[0])

        # 顶部边框
        result = "┌" + "─────┬" * (cols - 1) + "─────┐\n"

        for i in range(rows):
            result += "│"
            for j in range(cols):
                if grid[i][j] == 0:
                    result += "     │"
                else:
                    result += f" {grid[i][j]:2d}  │"
            result += "\n"

            # 分隔线
            if i < rows - 1:
                result += "├" + "─────┼" * (cols - 1) + "─────┤\n"

        # 底部边框
        result += "└" + "─────┴" * (cols - 1) + "─────┘\n"

        return result


def main():
    root = tk.Tk()
    app = ModernSwitchPuzzleGUI(root)
    root.mainloop()


if __name__ == "__main__":
    main()
